package cn.tonyqiu.gaecash.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.NotPersistent;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import cn.tonyqiu.gaecash.PMF;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.users.User;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Label extends BaseModel {

	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Key key;
	@Persistent 
	private String name;
	@Persistent
	private Set<String> bills;
	@Persistent
	private User user;
	@Persistent
	private Date createDate;
	@Persistent
	private Date modifiedDate;
	@NotPersistent
	private int count;
	@NotPersistent
	private String keyString;

	public Label() {
		this.createDate = new Date();
	}

	public Label(String name, User user) {
		this.name = name;
		this.user = user;
		this.createDate = new Date();
	}

	public int getCount() {
		if (bills == null)
			return 0;
		else {
			count = bills.size();
			return count;
		}
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public Key getKey() {
		return key;
	}

	public void setKey(Key key) {
		this.key = key;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set<String> getBills() {
		if (bills == null)
			bills = new HashSet<String>();
		return bills;
	}

	public void setBills(Set<String> bills) {
		this.bills = bills;
	}

	public Date getCreateDate() {
		return createDate;
	}

	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}

	public Date getModifiedDate() {
		return modifiedDate;
	}

	public void setModifiedDate(Date modifiedDate) {
		this.modifiedDate = modifiedDate;
	}

	public static Label getById(Long id) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Label label = pm.getObjectById(Label.class, id);
		return label;
	}

	@SuppressWarnings("unchecked")
	public static List<Label> getByLabelIds(Set<Key> set) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		List<Label> labels = new ArrayList<Label>();
		for (Key key : set) {
			labels.add(pm.getObjectById(Label.class, key.getId()));
		}
		return labels;
	}

	public static void del(String id) {
		Set<String> billSet = null;
		String labelKey = null;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Label label = pm.getObjectById(Label.class, id);
		billSet = label.getBills();
		labelKey = label.getKeyString();
		pm.deletePersistent(label);
		pm.close();

		pm = PMF.get().getPersistenceManager();
		pm.currentTransaction().begin();
		try {
			for (String billKey : billSet) {
				Bill bill = pm.getObjectById(Bill.class, billKey);
				bill.removeLabel(labelKey);
			}
			pm.currentTransaction().commit();
		} finally { 
			if (pm.currentTransaction().isActive())
				pm.currentTransaction().rollback();
			pm.close();
		}
	}

	@SuppressWarnings("unchecked")
	public void addBill(String billKey) {
		if (bills == null) {
			bills = new HashSet<String>();
		}
		bills.add(billKey);
	}

	@SuppressWarnings("unchecked")
	public void removeBill(String billKey) {
		if (bills != null) {
			bills.remove(billKey);
		}
	}

	@SuppressWarnings("unchecked")
	public void removeBill(Key billKey) {
		if (bills != null) {
			bills.remove(KeyFactory.keyToString(billKey));
		}
	}

	@SuppressWarnings("unchecked")
	public Label update() throws Exception {
		pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery("select from " + Label.class.getName());
		query.setFilter("user == paramUser");
		query.setFilter("name == paramName");
		query
				.declareParameters("java.lang.String paramUser,java.lang.String paramName");
		List<Label> labels = (List<Label>) query.execute(user, name);
		if (labels.size() >= 1)
			throw new LabelExistingException(name);
		Label orgLabel = pm.getObjectById(Label.class, getKeyString());
		orgLabel.setName(getName());
		orgLabel.setModifiedDate(new Date());
		pm.close();
		return orgLabel;
	}

	@SuppressWarnings("unchecked")
	public Label add() throws Exception {
		pm = PMF.get().getPersistenceManager();
		if (createDate == null) {
			createDate = new Date();
		}
		Query query = pm.newQuery("select from " + Label.class.getName());
		query.setFilter("user == paramUser && name == paramName");
		query
				.declareParameters("java.lang.String paramUser,java.lang.String paramName");
		List<Label> labels = (List<Label>) query.execute(user, name);
		if (labels.size() >= 1)
			throw new LabelExistingException(name);
		Label label = (Label) pm.makePersistent(this);
		return label;
	}

	@SuppressWarnings("unchecked")
	public static List<Label> getAll(User user) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		List<Label> labels = null;
		Query query = pm.newQuery("select from " + Label.class.getName());
		query.setOrdering("createDate desc");
		query.setFilter("user == paramUser");
		query.declareParameters("java.lang.String paramUser");
		labels = (List<Label>) query.execute(user);
		return labels;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public String getKeyString() {
		if (key != null)
			keyString = KeyFactory.keyToString(key);
		return keyString;
	}

	public void setKeyString(String keyString) {
		this.keyString = keyString;
	}
}
